import Image
import numpy as np
from itertools import product
import cma
from math import sin, cos, asin, acos, ceil
# deg 2 : 3 + 2 + 1 = 6
# deg 3 : 4 + 3 + 2 + 1 = 10
# deg 4 : 15
def tri(x):
	return asin(cos(x))

def car(x):
	return ceil(cos(x))

def product2(degre, rep):
	res=[]
	for row in product(range(degre+1), repeat=2):
		if sum(row) <= degre:
			res.append(row)
	return res

def createPoly(params, degre):
	return lambda x : sum([params[i] * x[0]**powers[0] * x[1]**powers[1] for i, powers in enumerate(product2(degre, 2))])

def createFunc(params):
	return lambda x : createPoly(params[:10], 3)(x) \
				+ params[10]*cos(params[11]*x[0]) + params[12]*cos(params[13]*x[0]) + params[13]*cos(params[14]*x[0]*x[1]) \
				+ params[15]*tri(params[16]*x[0]) + params[17]*tri(params[18]*x[0]) + params[19]*tri(params[20]*x[0]*x[1]) \

def ecartCarre(y1, y2):
	y1 = np.array(y1)
	y2 = np.array(y2)
	n = len(y1)
	ecart = y1-y2
	ecart = ecart**2
	ecart = ecart.sum()
	return ecart/n

imageFileName = "texture03nonUnif.jpg"
imageFileName = "texture02lisse.jpg"
imageFileName = "texture03lisse.jpg"
image = Image.open(imageFileName)
dataImage = list(image.getdata())
width = image.size[0]
height = image.size[1]

dataReg = []
red = []
green = []
blue = []
for i, (r, g, b) in enumerate(dataImage):
	x = i / width
	y = i % width
	dataReg.append([x, y]) #, cos(x), cos(y)])
	red.append(r)
	green.append(g)
	blue.append(b)

dataReg = np.array(dataReg)
dimF = 21

def fObj(x):
	xRed = x[:dimF]
	xGreen = x[dimF:dimF*2]
	xBlue = x[dimF*2:dimF*3]
	fRed = createFunc(xRed)
	fGreen = createFunc(xGreen)
	fBlue = createFunc(xBlue)
	redEstime = map(fRed, dataReg)
	greenEstime = map(fGreen, dataReg)
	blueEstime = map(fBlue, dataReg)
	ecartRed = ecartCarre(red, redEstime)
	ecartGreen = ecartCarre(green, greenEstime)
	ecartBlue = ecartCarre(blue, blueEstime)
	ecart = ecartRed + ecartGreen + ecartBlue
	print "DEBUG : fObj evaluated", ecart, x
	return ecart
	
if False:
	params0 = [0 for x in xrange(dimF*3)]
	sd0 = 10
	res_cma = cma.fmin(fObj, params0, sd0)
	print res_cma
#Restitution de l'image

x = [62.6233974611, -8.12747948438, 0.464248011748, -0.00363361063314, -47.9730058182, -0.0394366750131, 0.000591625309099, 1.86916958306, -0.00186253328453, -0.0163578837939, 74.6886135294, -44.1530992569, 40.349427427, 6.97354424745, -2.22526420035, -41.3018172257, 94.3775556227, 30.7136953159, 16.6709554352, -61.4635613218, 82.157196243, 36.1282083127, -0.906569473014, -0.25198929895, 0.00255833703691, 83.3982291384, -0.00563044056055, -0.00151574286376, -2.86394458213, 0.00377115367086, 0.0235553654937, 55.5919115987, -120.609256591, 53.6931969626, 36.2270648466, 51.5014231681, -22.4887673724, -26.6092390752, 48.3825112494, 22.1894003907, 25.6148048186, 3.94030469435, -17.8435804919, 62.7525266822, -1.37409916274, 0.00781045002082, -39.5567714809, -0.275726279688, 0.00489737255382, 1.0564419218, -0.00200711186183, -0.00730956335711, 71.548648467, 13.8500269729, -103.330012092, -4.81213268945, 9.53164980822, -10.6586422778, -62.276162101, 28.532939905, -79.1820190509, -101.156008464, 27.7268401984]
xRed = x[:dimF]
xGreen = x[dimF:dimF*2]
xBlue = x[dimF*2:dimF*3]
fRed = createFunc(xRed)
fGreen = createFunc(xGreen)
fBlue = createFunc(xBlue)
redEstime = map(fRed, dataReg)
greenEstime = map(fGreen, dataReg)
blueEstime = map(fBlue, dataReg)
redEstime = map(round, redEstime)
greenEstime = map(round, greenEstime)
blueEstime = map(round, blueEstime)
redEstime = map(int, redEstime)
greenEstime = map(int, greenEstime)
blueEstime = map(int, blueEstime)
dataNewImage = zip(redEstime, greenEstime, blueEstime)
newImage = Image.new(image.mode, image.size) 
newImage.putdata(dataNewImage) 

outImageFileName = imageFileName[:-4] + "_opt01" + imageFileName[-4:]
newImage.save(outImageFileName)
